package cn.com.huzo.webapp.controller;

import huzofw.common.web.controller.BaseFormController;
import huzofw.model.entities.identity.AccountViewEntity;
import huzofw.model.entities.identity.IdentityUserEntity;
import huzofw.service.security.IdentityUserManager;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

/**
 *
 * @author 吴旭
 */
@Controller
public class SignupController extends BaseFormController {

    @Resource
    private IdentityUserManager _manager;

    /**
     * 转到登录画面
     * <p>
     * @param req 上下文请求
     * @return
     */
    @RequestMapping("signup.html")
    public ModelAndView redirectSignupWnd(HttpServletRequest req) {
        ModelAndView view = new ModelAndView();
        // 为画面设置变量
        if (req.getParameter("kickout") != null) {
            view.addObject("msg", "您的帐号在另一个地点登录，您已被踢出。");
        }
        if (req.getParameter("forceLogout") != null) {
            view.addObject("msg", "您已经被管理员强制退出，请重新登录。");
        }
        view.setViewName("signup");

        return view;
    }

    /**
     * ajax登录 spring mvc 实现
     *
     * @param data 登录账户
     * @param request
     * @return
     * @throws java.lang.Exception
     */
    @SuppressWarnings("unchecked")
    @RequestMapping(value = "doAjaxSingup.html",
            method = RequestMethod.POST,
            produces = {"application/xml", "application/json"})
    public @ResponseBody
    Map<String, Object> handleAjaxLoginRequest(@RequestBody AccountViewEntity data, HttpServletRequest request) throws Exception {
        Map<String, Object> result = new HashMap(2);

        Subject currentUser = SecurityUtils.getSubject();
        Session session = currentUser.getSession();

        UsernamePasswordToken token = new UsernamePasswordToken(data.getUsername(), data.getPassword());
        token.setRememberMe(data.getRememberMe());

        try {
            // 获取了当前操作的Subject后，我们传入token，调用了login方法。一次login方法的调用，
            // 就代表尝试一次认证。
            currentUser.login(token);
            result.put("Success", true);
            result.put("Message", "登录成功：账号通过认证。");

            // 设置session内容
            IdentityUserEntity identityUser = _manager.fetchUserByName(data.getUsername());
            session.setAttribute("IdentityUser", identityUser);   // 设置Shiro的Session属性
        } catch (UnknownAccountException ex) {
            result.put("Success", false);
            result.put("Message", "登录失败：用户名错误。");
        } catch (IncorrectCredentialsException ex) {
            result.put("Success", false);
            result.put("Message", "登录失败：密码错误。");
        } catch (LockedAccountException ex) {
            result.put("Success", false);
            result.put("Message", "登录失败：账号已被锁定，请与系统管理员联系。");
        } catch (ExcessiveAttemptsException ex) {
            result.put("Success", false);
            result.put("Message", "登录失败：错误次数过多。");
        } catch (AuthenticationException ex) {
            result.put("Success", false);
            result.put("Message", ex.getMessage());
        }

        return result;
    }

    /**
     * 登录状态检查
     *
     * @return
     */
    @RequestMapping(value = "doAjaxCheckLoginStatus.html", method = RequestMethod.POST)
    public @ResponseBody
    String handleAjaxCheckLoginStatus() {
        Subject currentUser = SecurityUtils.getSubject();

        if (!currentUser.isAuthenticated()) {
            return "false";
        }

        return "true";
    }
}
